package singleton;

/**
 * 巧克力锅炉
 */
public class ChocolateBoiler {
    private boolean empty; // 锅炉内是否为空
    private boolean boiled; // 锅炉是否煮沸

//    private static ChocolateBoiler uniqueInstance;
//    private static ChocolateBoiler uniqueInstance = new ChocolateBoiler();
    private volatile static ChocolateBoiler uniqueInstance;

    private ChocolateBoiler() {
        empty = true; // 锅炉内为空
        boiled = false; // 锅炉未煮沸
    }

    // 获取唯一实例
    public static ChocolateBoiler getInstance() {
        if (uniqueInstance == null) { // 若为空，才需要进入区块
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            synchronized (ChocolateBoiler.class) { // 只有第一次进入才同步
                if(uniqueInstance == null) // 进入区块后，再次检查，若依然为空，则创建实例。
                    uniqueInstance = new ChocolateBoiler();
            }
        }
        return uniqueInstance;
    }

    // 填入巧克力
    public void fill() {
        // 获取当前线程名称
        System.out.printf("[INFO-%s] <fill> 正在填充巧克力。\n", Thread.currentThread().getName());

        if (isEmpty()) {
            empty = false; // 满了
            boiled = false; // 未煮沸
            System.out.printf("[INFO-%s] <fill> 巧克力已经填入锅炉。\n", Thread.currentThread().getName());
        }
    }

    // 排出
    public void drain() {
        System.out.printf("[INFO-%s] <drain> 巧克力已经煮沸，正在排出巧克力。\n", Thread.currentThread().getName());
        if (!isEmpty() && isBoiled()) {
            empty = true; // 空
            System.out.printf("[INFO-%s] <drain> 巧克力已经排出。\n", Thread.currentThread().getName());
        }
    }

    // 煮沸
    public void boil() {
        // 锅炉内不为空且未煮沸
        System.out.printf("[INFO-%s] <boil> 锅炉正在煮沸。\n", Thread.currentThread().getName());
        if (!isEmpty() && !isBoiled()) {
            boiled = true; // 煮沸
            System.out.printf("[INFO-%s] <boil> 巧克力已经煮沸。\n", Thread.currentThread().getName());
        }
    }

    public boolean isEmpty() {
        return empty;
    }

    public boolean isBoiled() {
        return boiled;
    }
}
